(function () {

    var config = {
        open: '{{',
        close: '}}'
    };
    var regEach1 = new RegExp("^\\s*each\\s+(?<name>.+?)(\\s+as\\s+(?<val>[\\w|\\$]+?)){0,1}(\\s*,\\s*(?<key>[\\w|\\$]+?)){0,1}(\\s*,\\s*(?<idx>[\\w|\\$]+?)){0,1}\\s*$");
    var regEach2 = new RegExp("^\\s*\\/each\\s*$");;
    var regIf1 = new RegExp("^\\s*if\\s+(.+)\\s*$");;
    var regIf2 = new RegExp("^\\s*\\/if\\s*$");;
    var regElse = new RegExp("^\\s*else\\s*$");;
    var regElseIf = new RegExp("^\\s*else\\s*if\\s+(.+)\\s*$");;
    var $sz = new RegExp("^((?!if|for|else|switch|case|break|{|}|var\\s+).)*$");; //不包含这些关键字

    var seq = 1; //序列值，用于记录each共处理多少次
    function uuid() {
        var s = [];
        var hexDigits = "0123456789abcdef";
        for (var i = 0; i < 8; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = "4";
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
        //s[8] = s[13] = s[18] = s[23] = "";

        var uuid = s.join("");
        return uuid;
    }

    /**
     * 模板渲染
     * @param {string} content 模板
     * @param {any} data 数据
     * @returns string
     */
    function render(content, data) {
        data = data || {};
        var list = ['this.tpl = "";'];

        for (var key in data){
            list.push('var '+key+'=data["'+key+'"]');
        }

        var codeArr = transform(content);  // 代码分割项数组

        for (var i = 0, len = codeArr.length; i < len; i++) {
            var item = codeArr[i]; // 当前分割项

            if (item.type === 1) {  // js逻辑

                //处理 each,if,else,elseif
                var match,block
                if (match = regEach1.exec(item.txt)) {
                    //console.log(match)
                    var items='items'+uuid()+seq++;
                    var name = match.groups.name
                    var val=match.groups.val||'val'
                    var key=match.groups.key||'key'
                    var idx=match.groups.idx||'index'
                    block = `var ${idx}=-1;var ${items}=${name};for(var ${key} in ${items}){ var ${val}=${items}[${key}];${idx}++;`;
                    list.push(block)
                } else if (match = regEach2.exec(item.txt)) {
                    list.push('}');
                } else if (match = regIf1.exec(item.txt)) {
                    block = 'if(' + match[1] + '){'
                    list.push(block)
                } else if (match = regIf2.exec(item.txt)) {
                    list.push('}')
                } else if (match = regElse.exec(item.txt)) {
                    list.push('}else{')
                } else if (match = regElseIf.exec(item.txt)) {
                    block = '}else if(' + match[1] + '){'
                    list.push(block)
                } else if ($sz.exec(item.txt)){ //匹配输出表达式
                    list.push('this.tpl+='+item.txt);
                }else{
                    list.push(item.txt);
                }

            } else if (item.type === 2) {  // js占位
                var txt = 'this.tpl+=' + item.txt + ';';
                list.push(txt);
            } else {  //文本
                var txt = 'this.tpl+="' +
                    item.txt.replace(/"/g, '\\"') +
                    '";';
                list.push(txt);
            }
        }

        list.push('return this.tpl;');
        //console.log(list.join('\n'))

        var obj = {
            fun:new Function('data', list.join('\n'))
        }

        return obj.fun(data);
    }

    /**
     * 从原始模板中提取 文本/js 部分
     * @param {string} content
     * @returns {Array<{type:number,txt:string}>}
     */
    function transform(content) {
        var arr = [];                 //返回的数组，用于保存匹配结果
        //var reg = /\{\{\s*((.|\n)*?)\s*\}\}/g;  //用于匹配js代码的正则
        var str = config.open+'\\s*((.|\\n)*?)\\s*'+config.close
        var reg = new RegExp(str,'g')

        var match;   				  //当前匹配到的match
        var nowIndex = 0;			  //当前匹配到的索引

        while (match = reg.exec(content)) {
            // 保存当前匹配项之前的普通文本/占位
            appendTxt(arr, content.substring(nowIndex, match.index));
            //保存当前匹配项
            var item = {
                type: 1,      // 类型  1- js代码块 2- js表达式 null- 文本
                txt: match[1] // 内容
            };
            var first = match[1].substr(0, 1);
            if (first == ':' || first == '=') {  // 如果是js占位
                item.type = 2;
                item.txt = item.txt.substr(1);
            }
            arr.push(item);
            //更新当前匹配索引
            nowIndex = match.index + match[0].length;
        }
        //console.log(content)
        //保存文本尾部
        appendTxt(arr, content.substr(nowIndex));
        return arr;
    }

    /**
     * 普通文本添加到数组，对换行部分进行转义
     *
     * @param {Array<{type:number,txt:string}>} list
     * @param {string} content
     */
    function appendTxt(list, content) {
        content = content.replace(/\r?\n/g, "\\n");
        list.push({txt: content});
    }

    window.cctpl={
        render:render,
        config:config,
    }

})();
